/*
 * Copyright 2023-2085 xujin <ceo@itgrail.com>
 *
 * Licensed under the Grail License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://itgrail.com/docs?id=3&catalogId=87
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.itgrail.pilot.app.command;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Preconditions;
import com.itgrail.pilot.app.command.cmo.*;
import com.itgrail.pilot.app.converter.AllCommentClientConverter;
import com.itgrail.pilot.app.converter.KeyCommentClientConverter;
import com.itgrail.pilot.app.converter.KeyResultClientConverter;
import com.itgrail.pilot.app.converter.ObjectiveClientConverter;
import com.itgrail.pilot.domain.user.entity.AllCommentE;
import com.itgrail.pilot.domain.user.entity.KeyCommentE;
import com.itgrail.pilot.domain.user.entity.KeyResultE;
import com.itgrail.pilot.domain.user.entity.ObjectiveE;
import com.itgrail.pilot.domain.user.enums.PeriodButtonTypeEnum;
import com.itgrail.pilot.infrastructure.tunnel.db.dao.OkrPeriodMapper;
import com.itgrail.pilot.infrastructure.tunnel.db.dao.UserMapper;
import com.itgrail.pilot.infrastructure.tunnel.db.dao.UserRolesMapper;
import com.itgrail.pilot.infrastructure.tunnel.db.dataobject.OkrPeriodDO;
import com.itgrail.pilot.infrastructure.tunnel.db.dataobject.UserDO;
import com.itgrail.pilot.infrastructure.tunnel.db.dataobject.UserRolesDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.itgrail.grail.cqrs.annotation.CmdHandler;
import com.itgrail.grail.cqrs.command.CommandExecutorI;
import com.itgrail.grail.dto.ResultData;
import com.itgrail.grail.exception.BusinessException;

import java.util.List;

@CmdHandler
@Slf4j
public class UpdateAllKeyResultCmdExe implements CommandExecutorI<ResultData, UpdateAllKeyResultCmd> {

    @Autowired
    private ObjectiveClientConverter objectiveClientConverter;

    @Autowired
    private KeyCommentClientConverter keyCommentClientConverter;

    @Autowired
    private AllCommentClientConverter allCommentClientConverter;

    @Autowired
    private KeyResultClientConverter keyResultClientConverter;

    @Autowired
    private OkrPeriodMapper okrPeriodMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRolesMapper userRolesMapper;

    @Override
    public ResultData execute(UpdateAllKeyResultCmd cmd) {
        log.info("更改keyResult信息:{}", JSON.toJSONString(cmd));
        ResultData resultData = new ResultData<>();
        UpdateObjectiveCmd updateObjectiveCmd = cmd.getUpdateObjectiveCmd();
        //判断当前KR所在周期的状态
        if (isAdmin(cmd.getCurrentUserId()) || isLockPeriodStatus(cmd)) {
            updateObjectiveCmd.setCurrentUserId(cmd.getCurrentUserId());
            Integer objectiveId = updateOrSaveObjective(updateObjectiveCmd);
            updateOrSaveKeyResult(cmd.getUpdateKeyResultCmds(), objectiveId, cmd.getCurrentUserId());
            resultData.setData(objectiveId);
        } else {
            throw new BusinessException("500", "当前KR已被锁定，不能操作");
        }

        return resultData;
    }

    protected Integer updateOrSaveObjective(UpdateObjectiveCmd updateObjectiveCmd) {
        ObjectiveE objectiveE = objectiveClientConverter.updateClientToEntity(updateObjectiveCmd);
        if (updateObjectiveCmd.getId() == null) {
            //新增
            objectiveE.setCreated(updateObjectiveCmd.getCurrentUserId());
            int save = objectiveE.save();
            objectiveE.setId(save);
        } else {
            //更新
            objectiveE.setUpdated(updateObjectiveCmd.getCurrentUserId());
            objectiveE.update();
        }
        AddAllCommentCmd addAllCommentCmd = updateObjectiveCmd.getAddAllCommentCmd();
        if (null != addAllCommentCmd) {
            AllCommentE allCommentE = allCommentClientConverter.addClientToEntity(addAllCommentCmd);
            allCommentE.save();
        }
        return objectiveE.getId();
    }

    protected void updateOrSaveKeyResult(List<UpdateKeyResultCmd> cmds, Integer objectiveId, Integer created) {
        cmds.forEach(x -> {
            KeyResultE keyResultE = keyResultClientConverter.updateClientToEntity(x);
            keyResultE.setObjectiveId(objectiveId);
            if (keyResultE.getId() == null) {
                keyResultE.setCreated(created);
                keyResultE.save();
            } else {
                keyResultE.setUpdated(created);
                keyResultE.update();
            }
            if (x.getAddKeyCommentCmd() != null) {
                KeyCommentE keyCommentE = keyCommentClientConverter.addClientToEntity(x.getAddKeyCommentCmd());
                keyCommentE.save();
            }
        });
    }

    protected boolean isLockPeriodStatus(UpdateAllKeyResultCmd cmd) {
        UpdateObjectiveCmd updateObjectiveCmd = cmd.getUpdateObjectiveCmd();
        if (updateObjectiveCmd != null) {
            OkrPeriodDO okrPeriodDO = okrPeriodMapper.selectById(updateObjectiveCmd.getOkrPeriodId());
            if (StringUtils.isNotEmpty(okrPeriodDO.getExtInfo())) {
                OkrPeriodButtonCmd okrPeriodButtonCmd = JSON.parseObject(okrPeriodDO.getExtInfo(), OkrPeriodButtonCmd.class);
                PeriodButtonTypeEnum buttonTypeEnum = PeriodButtonTypeEnum.getEnumByValue(cmd.getPeriodButtonType());
                if (buttonTypeEnum == null) {
                    return true;
                }
                switch (buttonTypeEnum) {
                    case OBJECTIVE_SWITCH:
                        return okrPeriodButtonCmd.isObjectiveSwitch();
                    case KEY_RESULT_SWITCH:
                        return okrPeriodButtonCmd.isKeyResultSwitch();
                    case WEIGHT_SWITCH:
                        return okrPeriodButtonCmd.isWeightSwitch();
                    case SCORE_SWITCH:
                        return okrPeriodButtonCmd.isScoreSwitch();
                    case LEADER_SWITCH:
                        return okrPeriodButtonCmd.isLeaderSwitch();
                    case MY_SWITCH:
                        return okrPeriodButtonCmd.isMySwitch();
                    case PLAN_SWITCH:
                        return okrPeriodButtonCmd.isPlanSwitch();
                }
            }
        }
        return true;
    }

    protected boolean isAdmin(Integer userId) {
        if (null == userId) {
            return false;
        }
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        UserDO userDO = userMapper.selectOne(queryWrapper);
        if (null != userDO && StringUtils.isNotEmpty(userDO.getAccount())) {
            QueryWrapper<UserRolesDO> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("username", userDO.getAccount());
            queryWrapper1.eq("role", "ADMIN");
            UserRolesDO userRolesDO = userRolesMapper.selectOne(queryWrapper1);
            if (null != userRolesDO) {
                return true;
            }
        }
        return false;
    }

    protected boolean check(UpdateAllKeyResultCmd cmd) {
        Preconditions.checkNotNull(cmd, "cmd不能为null");
        Preconditions.checkNotNull(cmd.getUpdateObjectiveCmd(), "objectiveCmd不能为null");
        return true;
    }
}
